#include "stm32f10x.h"                  // Device header

void MyCAN_Init(void)
{
	//1.RCC开始时钟，使用PA11和PA12，所以开始GPIOA的时钟
	//开始CAN外设的时钟，CAN外设挂载在APB1的
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
	
	//2.初始化GPIO口
	//PA12
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	//PA11
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	//CAN外设的初始化
	CAN_InitTypeDef CAN_InitStructure;//结构体
	CAN_InitStructure.CAN_Mode = CAN_Mode_LoopBack;//模式，环回测试模式，自发自收
	//波特率 = 36M / 48 / (1 + 2 + 3) = 125K
	CAN_InitStructure.CAN_Prescaler = 48;		//分配系数
	CAN_InitStructure.CAN_BS1 = CAN_BS1_2tq; //BS1段的Tq段
	CAN_InitStructure.CAN_BS2 = CAN_BS2_3tq; //BS2段的Tq段
	CAN_InitStructure.CAN_SJW = CAN_SJW_2tq; //再同步补偿宽度
	//这里不用我们手动减1，因为库函数已经帮我们处理好了
	CAN_InitStructure.CAN_NART = DISABLE;
	CAN_InitStructure.CAN_TXFP = DISABLE;
	CAN_InitStructure.CAN_RFLM = DISABLE;
	CAN_InitStructure.CAN_AWUM = DISABLE;
	CAN_InitStructure.CAN_TTCM = DISABLE;
	CAN_InitStructure.CAN_ABOM = DISABLE;
	CAN_Init(CAN1, &CAN_InitStructure);
	
	//配置过滤器
	CAN_FilterInitTypeDef CAN_FilterInitStructure;//结构体
	CAN_FilterInitStructure.CAN_FilterNumber = 0;//第几个过滤器被初始化
	//对应R1和R2
	CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;
	CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
	CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
	CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
	//对应R1和R2，这里配置位全通模式
	CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;//选择过滤器位宽
	CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;//选择过滤器模式
	CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0;//配置过滤器关联
	CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;//激活
	CAN_FilterInit(&CAN_FilterInitStructure);
}

//发送报文函数
void MyCAN_Transmit(uint32_t ID, uint8_t Length, uint8_t *Data)
{
	CanTxMsg TxMessage;
	TxMessage.StdId = ID;
	TxMessage.ExtId = ID;
	TxMessage.IDE = CAN_Id_Standard;		//CAN_ID_STD
	TxMessage.RTR = CAN_RTR_Data;
	TxMessage.DLC = Length;
	for (uint8_t i = 0; i < Length; i ++)
	{
		TxMessage.Data[i] = Data[i];
	}
	
	uint8_t TransmitMailbox = CAN_Transmit(CAN1, &TxMessage);//库函数
	
	uint32_t Timeout = 0;//计时变量
	while (CAN_TransmitStatus(CAN1, TransmitMailbox) != CAN_TxStatus_Ok)//库函数
	{
		Timeout ++;
		if (Timeout > 100000)//超时退出
		{
			break;
		}
	}
}

//查询是否有报文排队的函数
uint8_t MyCAN_ReceiveFlag(void)
{
	if (CAN_MessagePending(CAN1, CAN_FIFO0) > 0)//库函数
	{
		return 1;
	}
	return 0;
}

//接收报文函数
void MyCAN_Receive(uint32_t *ID, uint8_t *Length, uint8_t *Data)
{
	CanRxMsg RxMessage;
	CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);//库函数
	
	if (RxMessage.IDE == CAN_Id_Standard)
	{
		*ID = RxMessage.StdId;
	}
	else
	{
		*ID = RxMessage.ExtId;
	}
	
	if (RxMessage.RTR == CAN_RTR_Data)
	{
		*Length = RxMessage.DLC;
		for (uint8_t i = 0; i < *Length; i ++)
		{
			Data[i] = RxMessage.Data[i];
		}
	}
	else//收起到遥控帧不进行处理
	{
		//...
	}
}
